using CoreManager.API.Common;
using CoreManager.Core.Caching;
using CoreManager.Services.Captcha;
using CoreManager.Models.DTOs;
using CoreManager.Services.Auth;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace CoreManager.API.System.Controllers
{
    /// <summary>
    /// 认证控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    [AllowAnonymous] // 认证相关接口不需要鉴权
    public class AuthController : BaseController
    {
        private readonly IAuthService _authService;
        private readonly ICaptchaService _captchaService;
        private readonly ICacheService _cacheService;
        private readonly ILogger<AuthController> _logger;

        public AuthController(
            IAuthService authService, 
            ICaptchaService captchaService,
            ICacheService cacheService,
            ILogger<AuthController> logger) : base(logger)
        {
            _authService = authService;
            _captchaService = captchaService;
            _cacheService = cacheService;
            _logger = logger;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        [HttpPost("login")]
        public async Task<IActionResult> Login([FromBody] LoginDto loginDto)
        {
            try
            {
                // 验证验证码
                if (string.IsNullOrEmpty(loginDto.CaptchaCode) || string.IsNullOrEmpty(loginDto.RequestId))
                {
                    return BadRequest("验证码不能为空");
                }

                var isCaptchaValid = _captchaService.ValidateCaptcha(loginDto.RequestId, loginDto.CaptchaCode);
                if (!isCaptchaValid)
                {
                    return BadRequest("验证码错误或已过期");
                }

                var result = await _authService.LoginAsync(loginDto);
                if (result == null)
                {
                    return BadRequest("用户名或密码错误");
                }

                // 将token存入缓存 - 使用公共常量
                var cacheKey = CacheConstants.GetUserTokenKey(result.UserId);
                await _cacheService.SetAsync(cacheKey, result.AccessToken, CacheConstants.USER_TOKEN_EXPIRY);

                _logger.LogInformation("用户 {loginDto.UserName} 登录成功",loginDto.UserName);
                return Success(result, "登录成功");
            }
            catch (UnauthorizedAccessException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                return HandleException(ex, $"用户 {loginDto.UserName} 登录");
            }
        }

        /// <summary>
        /// 刷新令牌
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("refresh")]
        public async Task<IActionResult> RefreshToken([FromBody] RefreshTokenRequest request)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(request.RefreshToken))
                {
                    return BadRequest("刷新令牌不能为空");
                }
                var result = await _authService.RefreshTokenAsync(request.RefreshToken);
                return result == null ? Unauthorized("刷新令牌失败") : Success(result, "刷新令牌成功");
            }
            catch (ArgumentException ex)
            {
                _logger.LogWarning("刷新令牌参数错误: {Message}", ex.Message);
                return BadRequest(ex.Message);
            }
            catch (UnauthorizedAccessException ex)
            {
                _logger.LogWarning("刷新令牌未授权: {Message}", ex.Message);
                return Unauthorized(ex.Message);
            }
            catch (Exception ex)
            {
                return HandleException(ex, "刷新令牌");
            }
        }

        /// <summary>
        /// 用户登出
        /// </summary>
        /// <returns></returns>
        [HttpPost("logout")]
        [Authorize] // 登出需要鉴权
        public async Task<IActionResult> Logout()
        {
            try
            {
                var userId = GetCurrentUserId();
                await _authService.LogoutAsync(userId);
                
                _logger.LogInformation("用户 {userId} 登出成功",userId);
                return Success("登出成功");
            }
            catch (Exception ex)
            {
                return HandleException(ex, "用户登出");
            }
        }

        /// <summary>
        /// 获取当前用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("userinfo")]
        [Authorize] // 获取用户信息需要鉴权
        public async Task<IActionResult> GetUserInfo()
        {
            try
            {
                var userId = GetCurrentUserId();
                var userInfo = await _authService.GetCurrentUserAsync(userId);
                return userInfo == null ? NotFound("用户不存在") : Success(userInfo, "获取用户信息成功");
            }
            catch (Exception ex)
            {
                return HandleException(ex, "获取用户信息");
            }
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="changePasswordDto"></param>
        /// <returns></returns>
        [HttpPost("change-password")]
        [Authorize] // 修改密码需要鉴权
        public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordDto changePasswordDto)
        {
            try
            {
                var userId = GetCurrentUserId();
                var result = await _authService.ChangePasswordAsync(userId, changePasswordDto.OldPassword, changePasswordDto.NewPassword);
                
                if (!result)
                {
                    return BadRequest("旧密码错误");
                }

                _logger.LogInformation("用户 {userId} 修改密码成功",userId);
                return Success("密码修改成功");
            }
            catch (Exception ex)
            {
                return HandleException(ex, "修改密码");
            }
        }



    }

    /// <summary>
    /// 修改密码DTO
    /// </summary>
    public class ChangePasswordDto
    {
        /// <summary>
        /// 旧密码
        /// </summary>
        public string OldPassword { get; set; } = string.Empty;

        /// <summary>
        /// 新密码
        /// </summary>
        public string NewPassword { get; set; } = string.Empty;
    }

    /// <summary>
    /// 刷新令牌请求DTO
    /// </summary>
    public class RefreshTokenRequest
    {
        /// <summary>
        /// 刷新令牌
        /// </summary>
        public string RefreshToken { get; set; } = string.Empty;
    }
}